#if defined(OS_ANDROID)||defined(OS_LINUX_SOC)	
#define MSEPOLL_C
#include <sys/types.h>
#include <sys/stat.h>		//mkdir()
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
//user header
#include <libmslog/mslog.h>
#include "msepoll.h"
#include "mstime.h"
#include "mscommon.h"

#define FLAG "EPOLL"

#define msepoll_timeout_ms		500

ms_s32 msepoll_innerapi_open(ms_u32 ms_in ev_size,ms_cstring ms_in func,ms_u32 ms_in line)
{
	ms_s32 epfd=epoll_create(ev_size);
	//ms_info("[%s][%d]-------------%d", func,line,epfd);
	return epfd;
}
ms_s32 msepoll_add(ms_s32 ms_in epfd,ms_s32 ms_in ev_fd,ms_u32 ms_in opt)
{
	msepoll_event event;
	event.data.fd=ev_fd;
	event.events=opt;
	if(epoll_ctl(epfd, EPOLL_CTL_ADD, ev_fd, (msepoll_event *)&event)<0){
		ms_errRet(-1,"epoll_ctl add failed: %d %s",errno, strerror(errno));
	}else{
		//ms_debug("epoll_ctl %d add %d",epfd,ev_fd);
	}
	return 0;
}

ms_s32 msepoll_mod(ms_s32 ms_in epfd,ms_s32 ms_in ev_fd,ms_u32 ms_in opt)
{
	msepoll_event event;
	event.data.fd=ev_fd;
	event.events=opt;
	if(epoll_ctl(epfd, EPOLL_CTL_MOD, ev_fd, (msepoll_event *)&event)<0){
		ms_errRet(-1,"epoll_ctl mod failed: %d %s",errno, strerror(errno));
	}
	return 0;
}

ms_s32 msepoll_del(ms_s32 ms_in epfd,ms_s32 ms_in ev_fd,ms_u32 ms_in opt)
{
	if(-1==epfd){
		return 1;
	}
	msepoll_event event;
	event.data.fd=ev_fd;
	event.events=opt;
	if(epoll_ctl(epfd, EPOLL_CTL_DEL, ev_fd, (msepoll_event *)&event)<0){
		ms_errRet(-1,"epoll_ctl del failed: %d %s",errno, strerror(errno));
	}else{
		//ms_debug("epoll_ctl %d del %d",epfd,ev_fd);
	}
	return 0;
}
ms_s32 msepoll_wait(ms_s32 ms_in epfd, pmsepoll_event ms_io events, ms_u32 ms_in maxevents)
{
	return epoll_wait(epfd,events,maxevents,msepoll_timeout_ms);
}
ms_s32 msepoll_wait_timeout(ms_s32 ms_in epfd, pmsepoll_event ms_io  events, ms_u32 ms_in maxevents,ms_u32 ms_in timeout_ms)
{
	return epoll_wait(epfd,events,maxevents,timeout_ms);
}
ms_s32 msepoll_close(ms_s32 ms_in *epfd)
{
	//ms_info("-------------%d", (*epfd));
	ms_close((*epfd));
	(*epfd)=-1;
	return 0;
}
MSEPOLLRet msepoll_waitfd_timeout_noopt(ms_s32 ms_in epfd,ms_s32 ms_in ev_fd, ms_bool ms_in is_out,ms_u32 ms_in timeout_ms)
{
	ms_u32 event_index=0;
	ms_s32 event_num=0;
	ms_u32 opt= ((ms_true==is_out) ?msepollout : msepollin);
	msepoll_event msepoll_event[2];
	//ms_u32 ms_in timeout_ms_pertime=timeout_ms/10;
	ms_u64 time_base=mstime_api_us();
	while(1){
		memset(msepoll_event,0,sizeof(msepoll_event));
		ms_s32 event_num=msepoll_wait_timeout(epfd, msepoll_event, 2, 1000);
		if(event_num>0){
			for(event_index=0;event_index<event_num;event_index++){
				if(ev_fd!=msepoll_event[event_index].data.fd){
					continue;
				}
				if((msepoll_event[event_index].events&msepollhup)||(msepoll_event[event_index].events&msepollerr)){
					return msepoll_ret_abnormal_connection;
				}else if(msepoll_event[event_index].events&opt){
					return msepoll_ret_io_ok;
				}
			}		
		}
		if((mstime_api_us()-time_base)>(ms_usmseconds(timeout_ms))){
			return msepoll_ret_io_timeout;
		}
		ms_usleep((ms_usmseconds(timeout_ms))/100);
	}
}
MSEPOLLRet msepoll_waitfd_timeout(ms_s32 ms_in epfd,ms_s32 ms_in ev_fd, ms_bool ms_in is_out,ms_u32 ms_in timeout_ms)
{
	ms_u32 opt= ((ms_true==is_out) ?msepollout : msepollin);
	if(msepoll_add(epfd,ev_fd,opt)<0){
		return msepoll_ret_err_inner;
	}
	MSEPOLLRet ret =msepoll_waitfd_timeout_noopt(epfd,ev_fd,is_out, timeout_ms);
	if(msepoll_del(epfd,ev_fd,opt)<0){
		//如果存在连接状态异常，则优先报该状态
		if(msepoll_ret_abnormal_connection!=ret){
			ret=msepoll_ret_err_inner;
		}
	}
	return ret;
}


ms_s32 msepoll_appapi_init( ms_u32 num,void *callback_args ,ms_u32 ms_in opt,ms_s32 (*callback_func)(void *callback_args,ms_u32 index)){	
	ms_s32 epfd=-1;
	if( (epfd=msepoll_open((num+1)))<0	){
		ms_errRet(-1,"[Error] Cms msepoll_open failed");
	}
	ms_u32 index=0;
	for(index=0;index<num;index++){
		ms_s32 fd=callback_func(callback_args,index);
		if(fd>0){
			msepoll_add(epfd,fd,opt);
		}
	}
	return epfd;
}
ms_void msepoll_appapi_deinit( ms_s32 epfd,ms_u32 num,void *callback_args,ms_void (*callback_func)(void *callback_args,ms_u32 index)){	
	ms_u32 index=0;
	for(index=0;index<num;index++){
		callback_func(callback_args,index);
	}
	msepoll_close(&epfd);
}
ms_void msepoll_appapi_dataread( ms_s32 epfd,ms_u32 num ,void *callback_args,
	ms_void (*incallback_func)(void *callback_args,ms_s32 fd),
	ms_void (*outcallback_func)(void *callback_args,ms_s32 fd)){
	msepoll_event cms_event[(num+1)];
	ms_u64 task_time=mstime_api_us();
	while(ms_lessThan((mstime_api_us()-task_time), 1000000)){
		memset(cms_event,0,sizeof(msepoll_event));
		int event_num=msepoll_wait(epfd,(msepoll_event *)cms_event,(num+1));
		if(event_num>0){
			int event_index=0;
			for(event_index=0;event_index<event_num;event_index++){
				if(cms_event[event_index].events&msepollhup){
					ms_debug("cms-msepollhup");
				}else if(cms_event[event_index].events&msepollerr){
					ms_debug("cms-msepollerr");
				}else if(cms_event[event_index].events&msepollin){
					if(ms_null!=incallback_func){
						incallback_func(callback_args,cms_event[event_index].data.fd);
					}
				}else if(cms_event[event_index].events&msepollout){
					if(ms_null!=outcallback_func){
						outcallback_func(callback_args,cms_event[event_index].data.fd);
					}
				}
			}		
		}
		ms_msleep(1);
	}
}
#undef MSEPOLL_C
#endif
